﻿using System.Linq;
using System.Text;

namespace ThingsGateway.Foundation
{
    /// <summary>
    /// 所有数据转换类的静态辅助方法<br />
    /// </summary>
    public static class ByteConverterHelper
    {

        #region Public Methods

        /// <summary>
        ///设备地址可以带有的额外信息包含：
        /// DATA=XX;
        /// TEXT=XX;
        /// BCD=XX;
        /// LEN=XX;
        ///<br></br>
        /// 解析地址的附加<see cref="DataFormat"/> />参数方法，比如你的地址是dataformat=ABCD;D100，
        /// 可以提取出"dataformat"的值的同时，并去掉address中的全部额外信息，包含字符串信息等，
        /// 如果"dataformat"不存在的话，不修改<see cref="IByteConverter"/>对象<br />
        /// </summary>
        /// <param name="address">复杂的地址格式，比如：format=ABCD;x=3;s=1;100</param>
        /// <param name="defaultTransform">默认的数据转换信息</param>
        /// <returns>解析后的参数结果内容x=3;s=1;100</returns>
        public static IByteConverter ExtractTransformParameter(
          ref string address,
          IByteConverter defaultTransform)
        {
            try
            {
                string str1 = address;
                //设备地址可以带有的额外信息包含：
                // DATA=XX;
                // TEXT=XX;
                // BCD=XX;
                // LEN=XX;
                var strs = str1.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);

                //去除以上的额外信息
                address = String.Join(";", strs.Where(m =>
                (!m.Trim().ToUpper().Contains("DATA=")) &&
                (!m.Trim().ToUpper().Contains("TEXT=")) &&
                (!m.Trim().ToUpper().Contains("BCD=")) &&
                (!m.Trim().ToUpper().Contains("LEN="))
                ));

                for (int i = 0; i < strs.Length; i++)
                {
                    if (!strs[i].EndsWith(";"))
                    {
                        strs[i] += ";";
                    }
                }

                string format = String.Join(";", strs.Where(m =>
                m.Trim().ToUpper().Contains("DATA=") ||
                m.Trim().ToUpper().Contains("TEXT=") ||
                m.Trim().ToUpper().Contains("BCD=") ||
                m.Trim().ToUpper().Contains("LEN=")
                )
                 );
                //获取实际附加属性值
                var dict = format.GetExpressionsResult();

                DataFormat dataFormat = dict["DATA"] == null ?
                    defaultTransform.DataFormat :
                    (DataFormat)dict["DATA"];

                return dataFormat != defaultTransform.DataFormat ?
                    defaultTransform.CreateByDateFormat(dataFormat) :
                    defaultTransform;
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        ///设备地址可以带有的额外信息包含：
        /// DATA=XX;
        /// TEXT=XX;
        /// BCD=XX;
        /// LEN=XX;
        ///<br></br>
        /// 去掉address中的全部额外信息，包含字符串信息等，
        /// </summary>
        /// <param name="address">复杂的地址格式，比如：format=ABCD;x=3;s=1;100</param>
        public static void ExtractTransformParameter(
          ref string address)
        {
            string str1 = address;
            //设备地址可以带有的额外信息包含：
            // DATA=XX;
            // TEXT=XX;
            // BCD=XX;
            // LEN=XX;
            var strs = str1.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);

            //去除以上的额外信息
            address = String.Join(";", strs.Where(m =>
            (!m.Trim().ToUpper().Contains("DATA=")) &&
            (!m.Trim().ToUpper().Contains("TEXT=")) &&
            (!m.Trim().ToUpper().Contains("BCD=")) &&
            (!m.Trim().ToUpper().Contains("LEN="))
            ));

        }
        /// <summary>
        ///设备地址可以带有的额外信息包含：
        /// DATA=XX;
        /// TEXT=XX;
        /// BCD=XX;
        /// LEN=XX;
        ///<br></br>
        /// 解析全部参数方法
        /// 可以提取出参数值的同时，并去掉address中的全部额外信息
        /// 如果"dataformat"不存在的话，不修改<see cref="IByteConverter"/>对象<br />
        /// </summary>
        /// <param name="address">复杂的地址格式，比如：bcd=8421;format=ABCD;x=3;s=1;100</param>
        /// <param name="defaultTransform">默认的数据转换信息</param>
        /// <returns>解析后的参数结果内容x=3;s=1;100</returns>
        public static IByteConverter ExtractTransformParameter(
          ref string address,
          IByteConverter defaultTransform, out Encoding encoding, out ushort length, out BCDFormat bCDFormat)
        {
            try
            {
                string str1 = address;
                var strs = str1.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
                //去除以上的额外信息
                address = String.Join(";", strs.Where(m =>
                (!m.Trim().ToUpper().Contains("DATA=")) &&
                (!m.Trim().ToUpper().Contains("TEXT=")) &&
                (!m.Trim().ToUpper().Contains("BCD=")) &&
                (!m.Trim().ToUpper().Contains("LEN="))
                ));

                if (!strs[strs.Length - 1].EndsWith(";"))
                {
                    strs[strs.Length - 1] += ";";
                }

                string format = String.Join(";", strs.Where(m =>
                m.Trim().ToUpper().Contains("DATA=") ||
                m.Trim().ToUpper().Contains("TEXT=") ||
                m.Trim().ToUpper().Contains("BCD=") ||
                m.Trim().ToUpper().Contains("LEN=")
                )
                 );
                var dict = format.GetExpressionsResult();

                DataFormat dataFormat = dict["DATA"] == null ? defaultTransform.DataFormat : (DataFormat)dict["data"];
                encoding = dict["TEXT"] == null ? null : (Encoding)dict["TEXT"];
                length = Convert.ToUInt16(dict["LEN"].ToString());
                bCDFormat = dict["BCD"] == null ? BCDFormat.C8421 : (BCDFormat)dict["BCD"];

                return dataFormat != defaultTransform.DataFormat ?
                    defaultTransform.CreateByDateFormat(dataFormat) :
                    defaultTransform;
            }
            catch
            {
                throw;
            }
        }


        /// <summary>结果转换操作的基础方法，需要支持类型，及转换的委托</summary>
        /// <typeparam name="TResult">结果类型</typeparam>
        /// <param name="result">源结果</param>
        /// <returns>转换结果</returns>
        public static Result<TResult> GetResultFromArray<TResult>(
          Result<TResult[]> result)
        {
            return GetSuccessResultFromOther(result, m => m[0]);
        }

        /// <summary>结果转换操作的基础方法，需要支持类型，及转换的委托，并捕获转换时的异常方法</summary>
        /// <typeparam name="TResult">结果类型</typeparam>
        /// <param name="result">源</param>
        /// <param name="translator">实际转换的委托</param>
        /// <returns>转换结果</returns>
        public static Result<TResult> GetResultFromBytes<TResult>(
          Result<byte[]> result,
          Func<byte[], TResult> translator)
        {
            try
            {
                return result.IsSuccess ? Result.CreateSuccessResult(translator(result.Content)) : result.Copy<TResult>();
            }
            catch (Exception ex)
            {
                Result<TResult> resultFromBytes = new Result<TResult>
                {
                    Message = string.Format("{0} {1} : Length({2}) {3}", Resource.DataTransformError, result.Content.ToHexString(), result.Content.Length, ex.Message)
                };
                return resultFromBytes;
            }
        }

        /// <summary>使用指定的转换方法，来获取到实际的结果对象内容</summary>
        public static Result GetResultFromOther<TIn>(
          Result<TIn> result,
          Func<TIn, Result> trans)
        {
            return !result.IsSuccess ? result : trans(result.Content);
        }

        /// <summary>使用指定的转换方法，来获取到实际的结果对象内容</summary>
        public static Result<TResult> GetResultFromOther<TResult, TIn>(
          Result<TIn> result,
          Func<TIn, Result<TResult>> trans)
        {
            return !result.IsSuccess ? result.Copy<TResult>() : trans(result.Content);
        }



        /// <summary>使用指定的转换方法，来获取到实际的结果对象内容，所转换的规则</summary>
        public static Result<TResult> GetSuccessResultFromOther<TResult, TIn>(
          Result<TIn> result,
          Func<TIn, TResult> trans)
        {
            return !result.IsSuccess ? result.Copy<TResult>() : Result.CreateSuccessResult(trans(result.Content));
        }

        #endregion Public Methods

    }
}